/**
 * Copyright 2010-present Facebook.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.nhn.productmyself.lib;

import java.security.Permissions;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import android.app.ProgressDialog;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.text.TextUtils;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

import com.facebook.FacebookException;
import com.facebook.FacebookOperationCanceledException;
import com.facebook.LoggingBehavior;
import com.facebook.Session;
import com.facebook.Session.StatusCallback;
import com.facebook.SessionState;
import com.facebook.Settings;
import com.facebook.model.GraphUser;
import com.facebook.widget.UserSettingsFragment;
import com.facebook.widget.WebDialog;
import com.facebook.widget.WebDialog.OnCompleteListener;
import com.nhn.productmyself.lib.common.LogManager;
import com.sromku.simple.fb.SimpleFacebook;
import com.sromku.simple.fb.entities.Feed;
import com.sromku.simple.fb.entities.Profile;
import com.sromku.simple.fb.entities.Profile.Properties;
import com.sromku.simple.fb.listeners.OnProfileListener;
import com.sromku.simple.fb.listeners.OnPublishListener;

public class FacebookLoginUsingFragmentActivity extends FragmentActivity implements OnClickListener {

	public static final String TAG = FacebookLoginUsingFragmentActivity.class.getSimpleName();
	private static final int PICK_FRIENDS_ACTIVITY = 1;
	private UserSettingsFragment mUserSettingsFragment;
	private SimpleFacebook mSimpleFacebook;
	private Button mBtnFriendPicker;
	private Button mBtnLoginLogout;
	private ProgressDialog mProgressDialog;
	private SimpleDialogFragment mDialogFragment;
	
	private boolean mPickFriendsWhenSessionOpened;
	private String mUserId;

	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.facebook_login_fragment_activity);
		
		mDialogFragment = new SimpleDialogFragment();

		FragmentManager fragmentManager = getSupportFragmentManager();
		mUserSettingsFragment = (UserSettingsFragment) fragmentManager.findFragmentById(R.id.login_fragment);
		mBtnFriendPicker = mUserSettingsFragment.getFriendPickerButton();
		mBtnLoginLogout = mUserSettingsFragment.getLoginLogoutButton();
		mBtnFriendPicker.setText("Chọn bạn bè để tag");
		mBtnFriendPicker.setOnClickListener(this);
		mBtnLoginLogout.setOnClickListener(this);
		mUserSettingsFragment.setSessionStatusCallback(mStatusCallback);
		
		// restore connection state
		Settings.addLoggingBehavior(LoggingBehavior.INCLUDE_ACCESS_TOKENS);
        Session session = Session.getActiveSession();
        if (session == null) {
            if (savedInstanceState != null) {
                session = Session.restoreSession(this, null, mStatusCallback, savedInstanceState);
            } 
            if (session == null) {
                session = new Session(this);
            }
            Session.setActiveSession(session);
            if (session.getState().equals(SessionState.CREATED_TOKEN_LOADED)) {
                session.openForRead(new Session.OpenRequest(this).setCallback(mStatusCallback));
            }
        }
        updateView();
	}
	
	private void onClickLogin() {
		if (findFacebookClient() != null) {
			Session session = Session.getActiveSession();
			if (!session.isOpened() && !session.isClosed()) {
				session.openForRead(new Session.OpenRequest(this).setCallback(mStatusCallback));
			} else {
				Session.openActiveSession(this, true, mStatusCallback);
			}
		} else {
			if (mDialogFragment != null) {
				Bundle argBundle = new Bundle();
				argBundle.putString(SimpleDialogFragment.KEY_DIALOG_MESSAGE,
						"Vui lòng cài ứng dụng Facebook trước khi sử dụng chức năng này.");
				mDialogFragment.setArguments(argBundle);
				mDialogFragment.show(getSupportFragmentManager(), SimpleDialogFragment.TAG_DIALOG_ID);
			}
		}
	}

    private void onClickLogout() {
        Session session = Session.getActiveSession();
        if (!session.isClosed()) {
            session.closeAndClearTokenInformation();
        }
    }

	@Override
	protected void onResume() {
		super.onResume();
		mSimpleFacebook = SimpleFacebook.getInstance(this);
	}
	
    @Override
    public void onStart() {
        super.onStart();
        Session.getActiveSession().addCallback(mStatusCallback);
    }

    @Override
    public void onStop() {
        super.onStop();
        Session.getActiveSession().removeCallback(mStatusCallback);
    }
	
	/**
	 * Update view.
	 */
	private void updateView() {
        Session session = Session.getActiveSession();
        if (session.isOpened()) {
            mBtnLoginLogout.setText("Đăng xuất");
			mPickFriendsWhenSessionOpened = true;
			mBtnFriendPicker.setVisibility(View.VISIBLE);
        } else {
        	mBtnLoginLogout.setText("Đăng nhập");
			mPickFriendsWhenSessionOpened = false;
			mBtnFriendPicker.setVisibility(View.GONE);
        }
    }

	@Override
	public void onActivityResult(int requestCode, int resultCode, Intent data) {
		mSimpleFacebook.onActivityResult(this, requestCode, resultCode, data);
		mUserSettingsFragment.onActivityResult(requestCode, resultCode, data);
		switch (requestCode) {
		case PICK_FRIENDS_ACTIVITY:
			LogManager.debug(TAG, "PICK_FRIENDS_ACTIVITY");
			handleAfterPickingFriends(resultCode);
			break;
		default:
			Session.getActiveSession().onActivityResult(this, requestCode, resultCode, data);
			break;
		}
	}

	private void handleAfterPickingFriends(int resultCode) {
		String results = "";
		ArrayList<String> userIDs = new ArrayList<String>();
		Collection<GraphUser> selection = ValueContainer.getInstance().getSelectedUsers();
		if (selection != null && selection.size() > 0) {
			for (GraphUser user : selection) {
				userIDs.add(user.getId());
				LogManager.debug(TAG, "username: " + user.getName());
			}
			results = TextUtils.join(",", userIDs);
		}
		LogManager.debug(TAG, "result: " + results);
//		sendFeedDialog(results);
		publishFeedInMyWall(userIDs);
//		sendRequestDialog(results);
	}

	public OnPublishListener onPublishListener = new OnPublishListener() {
		@Override
		public void onComplete(String postId) {
			LogManager.infor(TAG, "Published successfully. The new post id = " + postId);
		}
	};
	
	public OnProfileListener onProfileListener = new OnProfileListener() {
		@Override
		public void onComplete(Profile profile) {
			LogManager.infor(TAG, "My profile id = " + profile.getId());
			mUserId = profile.getId();
		}
	};
	
	/**
	 * Gets the my profile.
	 *
	 * @return the my profile
	 */
	public void getMyProfile() {
		Profile.Properties properties = new Profile.Properties.Builder()
		.add(Properties.ID)
		.add(Properties.FIRST_NAME)
		.add(Properties.COVER).add(Properties.WORK)
		.add(Properties.EDUCATION)
		.add(Properties.PICTURE).build();
		mSimpleFacebook.getProfile(properties, onProfileListener);
	}

	/**
	 * Publish feed <br>
	 * Must use {@link Permissions#PUBLISH_ACTION}
	 */
	public void publishFeedInMyWall(ArrayList<String> userIds) {
		// listener for publishing action
		final OnPublishListener onPublishListener = new OnPublishListener() {

			@Override
			public void onFail(String reason) {
				hideDialog();
				// insure that you are logged in before publishing
				LogManager.warning(TAG, "Failed to publish");
			}

			@Override
			public void onException(Throwable throwable) {
				hideDialog();
				LogManager.error(TAG, "Bad thing happened", throwable);
			}

			@Override
			public void onThinking() {
				// show progress bar or something to the user while publishing
				showDialog();
			}

			@Override
			public void onComplete(String postId) {
				hideDialog();
				toast("Published successfully. The new post id = " + postId);
			}
		};

		// feed builder
		Feed.Builder feedBuilder = new Feed.Builder();
		if (!TextUtils.isEmpty(ValueContainer.getInstance().getMessageContent())) {
			feedBuilder.setMessage(ValueContainer.getInstance().getMessageContent());
		}
		if (!TextUtils.isEmpty(ValueContainer.getInstance().getMessageName())) {
			feedBuilder.setName(ValueContainer.getInstance().getMessageName());
		}
		if (!TextUtils.isEmpty(ValueContainer.getInstance().getMessageCaption())) {
			feedBuilder.setCaption(ValueContainer.getInstance().getMessageCaption());
		}
		if (!TextUtils.isEmpty(ValueContainer.getInstance().getMessageDescription())) {
			feedBuilder.setDescription(ValueContainer.getInstance().getMessageDescription());
		}
		if (userIds != null && userIds.size() > 0) {
			feedBuilder.setToUser(userIds);
		} else {
			feedBuilder.setToUser(new ArrayList<String>());
		}
	    feedBuilder.setLink(ValueContainer.FULL_LINKTO_APPLICATION);
	    
	    // show toast to introduce user
	    Toast.makeText(getApplicationContext(), "Bạn có thể Dán tin nhắn đã copy bằng cách nhấn & giữ ở ô Nhập nội dung", Toast.LENGTH_LONG).show();
	    
		// click on button and publish
		mSimpleFacebook.publish(feedBuilder.build(), true, onPublishListener);
	}

	/**
	 * Send request dialog.
	 */
	public void sendRequestDialog(String userId) {
		Bundle params = new Bundle();
		params.putString("message", "Learn how to make your Android apps social");

		WebDialog requestsDialog = (new WebDialog.RequestsDialogBuilder(FacebookLoginUsingFragmentActivity.this, Session.getActiveSession(),
				params)).setOnCompleteListener(new OnCompleteListener() {

			@Override
			public void onComplete(Bundle values, FacebookException error) {
				if (error != null) {
					if (error instanceof FacebookOperationCanceledException) {
						Toast.makeText(getApplicationContext(), "Request cancelled", Toast.LENGTH_SHORT)
								.show();
					} else {
						Toast.makeText(getApplicationContext(), "Network Error", Toast.LENGTH_SHORT)
								.show();
					}
				} else {
					final String requestId = values.getString("request");
					if (requestId != null) {
						Toast.makeText(getApplicationContext(), "Request sent", Toast.LENGTH_SHORT)
								.show();
					} else {
						Toast.makeText(getApplicationContext(), "Request cancelled", Toast.LENGTH_SHORT)
								.show();
					}
				}
			}

		}).build();
		requestsDialog.show();
	}

	/**
	 * Send feed dialog.
	 * 
	 * @param userIDs
	 *            the user id
	 */
	public void sendFeedDialog(String userIDs) {
		Bundle params = new Bundle();
		if (!TextUtils.isEmpty(ValueContainer.getInstance().getMessageName())) {
			params.putString("name", ValueContainer.getInstance().getMessageName());
		}
		if (!TextUtils.isEmpty(ValueContainer.getInstance().getMessageCaption())) {
			params.putString("caption", ValueContainer.getInstance().getMessageCaption());
		}
		if (!TextUtils.isEmpty(ValueContainer.getInstance().getMessageDescription())) {
			params.putString("description", ValueContainer.getInstance().getMessageDescription());
		}
		if (!TextUtils.isEmpty(mUserId)) {
			params.putString("from", mUserId);
		}
		params.putString("link", "https://developers.facebook.com/android");
		params.putString("picture", "https://raw.github.com/fbsamples/ios-3.x-howtos/master/Images/iossdk_logo.png");
		if (!TextUtils.isEmpty(userIDs)) {
			params.putString("to", userIDs);
		}
//		Session.getActiveSession().requestNewPublishPermissions(
//				new NewPermissionsRequest(FacebookLoginUsingFragmentActivity.this, CommonUtils
//						.arrayToList(ValueContainer.getInstance().getPublicPermission())));
		WebDialog feedDialog = (new WebDialog.FeedDialogBuilder(this, Session.getActiveSession(), params))
				.setOnCompleteListener(new OnCompleteListener() {

					@Override
					public void onComplete(Bundle values, FacebookException error) {
						if (error == null) {
							// When the story is posted, echo the success
							// and the post Id.
							final String postId = values.getString("post_id");
							if (postId != null) {
								Toast.makeText(getApplicationContext(), "Posted story, id: " + postId,
										Toast.LENGTH_SHORT).show();
							} else {
								// User clicked the Cancel button
								Toast.makeText(getApplicationContext(), "Publish cancelled", Toast.LENGTH_SHORT).show();
							}
						} else if (error instanceof FacebookOperationCanceledException) {
							// User clicked the "x" button
							Toast.makeText(getApplicationContext(), "Publish cancelled", Toast.LENGTH_SHORT).show();
						} else {
							// Generic, ex: network error
							Toast.makeText(getApplicationContext(), "Error posting story", Toast.LENGTH_SHORT).show();
						}
					}
				}).build();
		feedDialog.show();
	}

	@Override
	protected void onDestroy() {
		Session.getActiveSession().close();
		super.onDestroy();
	}

	@Override
	public void onClick(View v) {
		if (v.equals(mBtnFriendPicker)) {
			startPickFriendsActivity();
		} else if (v.equals(mBtnLoginLogout)) {
			Session session = Session.getActiveSession();
			if (session.isOpened()) {
				onClickLogout();
			} else {
				onClickLogin();
			}
		}
	}

	/**
	 * Ensure open session.
	 *
	 * @return true, if successful
	 */
	private boolean ensureOpenSession() {
		if (Session.getActiveSession() == null || !Session.getActiveSession().isOpened()) {
			Session.openActiveSession(this, true, new Session.StatusCallback() {
				@Override
				public void call(Session session, SessionState state, Exception exception) {
					onSessionStateChanged(session, state, exception);
				}
			});
			return false;
		}
		return true;
	}

	private void onSessionStateChanged(Session session, SessionState state, Exception exception) {
		if (mPickFriendsWhenSessionOpened && state.isOpened()) {
			mPickFriendsWhenSessionOpened = false;

			startPickFriendsActivity();
		}
	}

	private void startPickFriendsActivity() {
		if (ensureOpenSession()) {
			Intent intent = new Intent(this, FacebookPickFriendsActivity.class);
			FacebookPickFriendsActivity.populateParameters(intent, null, true, true);
			startActivityForResult(intent, PICK_FRIENDS_ACTIVITY);
		} else {
			mPickFriendsWhenSessionOpened = true;
		}
	}

	/**
	 * Show dialog.
	 */
	private void showDialog() {
		mProgressDialog = ProgressDialog.show(this, null, "Waiting for Facebook", true);
	}

	/**
	 * Hide dialog.
	 */
	private void hideDialog() {
		if (mProgressDialog != null) {
			mProgressDialog.hide();
		}
	}
	
	/**
	 * Show toast
	 * 
	 * @param message
	 */
	private void toast(String message) {
		Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
	}
	
	private Session.StatusCallback mStatusCallback = new StatusCallback() {
		
		@Override
		public void call(Session session, SessionState state, Exception exception) {
			LogManager.debug(TAG, String.format("New session state: %s", state.toString()));
			updateView();
		}
	};
	
	/**
	 * Find facebook client.
	 *
	 * @return the intent
	 */
	public Intent findFacebookClient()
	{
	    final String[] FacebookApps = {"com.facebook.android", "com.facebook.katana"};
	    Intent facebookIntent = new Intent();
	    facebookIntent.setType("text/plain");
	    final PackageManager packageManager = getPackageManager();
	    List<ResolveInfo> list = packageManager.queryIntentActivities(facebookIntent, PackageManager.MATCH_DEFAULT_ONLY);

	    for (int i = 0; i < FacebookApps.length; i++)
	    {
	        for (ResolveInfo resolveInfo : list)
	        {
	            String p = resolveInfo.activityInfo.packageName;
	            if (p != null && p.startsWith(FacebookApps[i]))
	            {
	                facebookIntent.setPackage(p);
	                return facebookIntent;
	            }
	        }
	    }
	    return null;
	}

}
